#include "mpp.h"
#include "v4l2.h"
#include <chrono>
#include <mutex>

// Global stream contexts (mp4/rtmp)
StreamContext mp4_ctx;
StreamContext rtmp_ctx;

// RKMPP global variables
MppCtx mpp_ctx = NULL;
MppApi *mpi = NULL;
MppBufferGroup buf_grp = NULL;
MppBuffer frm_buf = NULL;
MppBuffer pkt_buf = NULL;

// Mutex for MPP resources
std::mutex mpp_mutex;
std::mutex rtmp_ctx_mutex;

// Debug file for saving stream data
static FILE *debug_file = nullptr;
void cleanup_mpp(StreamContext &ctx) ;
static int init_mpp(MppEncCfg &cfg, size_t frame_size) {
    MPP_RET ret = MPP_OK;
    MppPollType timeout = MPP_POLL_BLOCK;

    std::lock_guard<std::mutex> lock(mpp_mutex);

    ret = mpp_create(&mpp_ctx, &mpi);
    if (MPP_OK != ret) {
        mpp_err("创建MPP失败\n");
        return -1;
    }

    ret = mpp_init(mpp_ctx, MPP_CTX_ENC, MPP_VIDEO_CodingAVC);
    if (MPP_OK != ret) {
        mpp_err("初始化MPP失败\n");
        return -1;
    }

    ret = mpp_enc_cfg_init(&cfg);
    if (MPP_OK != ret) {
        mpp_err("初始化编码器配置失败\n");
        return -1;
    }

    ret = mpi->control(mpp_ctx, MPP_ENC_GET_CFG, cfg);
    if (MPP_OK != ret) {
        mpp_err("获取默认编码器配置失败\n");
        return -1;
    }

    mpp_enc_cfg_set_s32(cfg, "prep:width", WIDTH);
    mpp_enc_cfg_set_s32(cfg, "prep:height", HEIGHT);
    mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", WIDTH);
    mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", HEIGHT);
    mpp_enc_cfg_set_s32(cfg, "prep:format", MPP_FMT_YUV420SP);

    mpp_enc_cfg_set_s32(cfg, "rc:mode", MPP_ENC_RC_MODE_CBR);
    mpp_enc_cfg_set_s32(cfg, "rc:bps_target", BITRATE);
    mpp_enc_cfg_set_s32(cfg, "rc:bps_max", BITRATE * 17 / 16);
    mpp_enc_cfg_set_s32(cfg, "rc:bps_min", BITRATE * 15 / 16);
    mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", FPS);
    mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denom", 1);
    mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", FPS);
    mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denom", 1);
    mpp_enc_cfg_set_s32(cfg, "rc:gop", FPS / 8); // 0.125秒一个关键帧

    mpp_enc_cfg_set_s32(cfg, "codec:type", MPP_VIDEO_CodingAVC);
    mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
    mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
    mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
    mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
    mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);

    mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 26);
    mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51);
    mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10);
    mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51);
    mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10);
    mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2);

    ret = mpi->control(mpp_ctx, MPP_ENC_SET_CFG, cfg);
    if (MPP_OK != ret) {
        mpp_err("设置编码器配置失败\n");
        return -1;
    }

    ret = mpi->control(mpp_ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout);
    if (MPP_OK != ret) {
        mpp_err("设置输出超时失败\n");
        return -1;
    }

    ret = mpp_buffer_group_get_internal(&buf_grp, MPP_BUFFER_TYPE_DRM);
    if (MPP_OK != ret) {
        mpp_err("获取缓冲区组失败\n");
        return -1;
    }

    ret = mpp_buffer_get(buf_grp, &frm_buf, frame_size);
    if (MPP_OK != ret) {
        mpp_err("获取帧缓冲区失败\n");
        return -1;
    }

    ret = mpp_buffer_get(buf_grp, &pkt_buf, frame_size);
    if (MPP_OK != ret) {
        mpp_err("获取数据包缓冲区失败\n");
        return -1;
    }

    return 0;
}

static int init_avformat(StreamContext &ctx, const char *url, const char *format, bool is_streaming) {
    av_log_set_level(AV_LOG_DEBUG); // 启用 FFmpeg 调试日志
    std::cerr << "初始化 AVFormat，目标: " << url << std::endl;

    ctx.fmt_ctx = nullptr;
    ctx.stream = nullptr;
    ctx.sws_ctx = nullptr;
    ctx.is_streaming = false;

    if (avformat_alloc_output_context2(&ctx.fmt_ctx, NULL, format, url) < 0) {
        std::cerr << "无法创建输出上下文: " << url << std::endl;
        return -1;
    }

    ctx.stream = avformat_new_stream(ctx.fmt_ctx, NULL);
    if (!ctx.stream || !ctx.stream->codecpar) {
        std::cerr << "无法创建视频流或 codecpar" << std::endl;
        avformat_free_context(ctx.fmt_ctx);
        ctx.fmt_ctx = nullptr;
        return -1;
    }

    ctx.stream->codecpar->codec_id = AV_CODEC_ID_H264;
    ctx.stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
    ctx.stream->codecpar->width = WIDTH;
    ctx.stream->codecpar->height = HEIGHT;
    ctx.stream->codecpar->format = AV_PIX_FMT_YUV420P;
    ctx.stream->codecpar->bit_rate = BITRATE;
    ctx.stream->time_base = (AVRational){1, FPS};

    if (is_streaming) {
        av_opt_set(ctx.fmt_ctx->priv_data, "rtmp_buffer", "100", 0);
        av_opt_set(ctx.fmt_ctx->priv_data, "rtmp_flush_interval", "100", 0);
        av_opt_set(ctx.fmt_ctx->priv_data, "preset", "ultrafast", 0);
        av_opt_set(ctx.fmt_ctx->priv_data, "tune", "zerolatency", 0);
        av_opt_set(ctx.fmt_ctx->priv_data, "flvflags", "no_duration_filesize", 0);
        av_opt_set(ctx.fmt_ctx->priv_data, "rtmp_live", "live", 0); // 明确直播模式

        MppPacket sps_pps_packet = NULL;
        if (mpp_packet_init(&sps_pps_packet, NULL, 0) != MPP_OK) {
            std::cerr << "初始化 SPS/PPS packet 失败" << std::endl;
            avformat_free_context(ctx.fmt_ctx);
            ctx.fmt_ctx = nullptr;
            ctx.stream = nullptr;
            return -1;
        }

        {
            std::lock_guard<std::mutex> lock(mpp_mutex);
            std::cerr << "获取 SPS/PPS，锁定 mpp_mutex" << std::endl;
            if (mpi->control(mpp_ctx, MPP_ENC_GET_EXTRA_INFO, &sps_pps_packet) != MPP_OK) {
                std::cerr << "获取 SPS/PPS 失败" << std::endl;
                mpp_packet_deinit(&sps_pps_packet);
                avformat_free_context(ctx.fmt_ctx);
                ctx.fmt_ctx = nullptr;
                ctx.stream = nullptr;
                return -1;
            }

            size_t packet_len = mpp_packet_get_length(sps_pps_packet);
            if (packet_len > 0) {
                ctx.stream->codecpar->extradata = static_cast<uint8_t*>(av_malloc(packet_len));
                if (!ctx.stream->codecpar->extradata) {
                    std::cerr << "无法分配 extradata 内存" << std::endl;
                    mpp_packet_deinit(&sps_pps_packet);
                    avformat_free_context(ctx.fmt_ctx);
                    ctx.fmt_ctx = nullptr;
                    ctx.stream = nullptr;
                    return -1;
                }
                ctx.stream->codecpar->extradata_size = packet_len;
                memcpy(ctx.stream->codecpar->extradata, mpp_packet_get_data(sps_pps_packet), packet_len);
                std::cerr << "extradata 内容: ";
                for (size_t i = 0; i < packet_len && i < 16; i++) {
                    std::cerr << std::hex << (int)ctx.stream->codecpar->extradata[i] << " ";
                }
                std::cerr << std::dec << std::endl;
            }
            mpp_packet_deinit(&sps_pps_packet);
        }
    }

    if (!(ctx.fmt_ctx->oformat->flags & AVFMT_NOFILE)) {
        int ret = avio_open(&ctx.fmt_ctx->pb, url, AVIO_FLAG_WRITE);
        if (ret < 0) {
            char err_buf[128];
            av_strerror(ret, err_buf, sizeof(err_buf));
            std::cerr << "无法打开输出: " << url << " - " << err_buf << std::endl;
            avformat_free_context(ctx.fmt_ctx);
            ctx.fmt_ctx = nullptr;
            return -1;
        }
    }

    AVDictionary *opts = NULL;
    if (is_streaming) {
        av_dict_set(&opts, "flvflags", "add_keyframe_index", 0);
    }

    if (avformat_write_header(ctx.fmt_ctx, &opts) < 0) {
        std::cerr << "无法写入文件头" << std::endl;
        av_dict_free(&opts);
        if (!(ctx.fmt_ctx->oformat->flags & AVFMT_NOFILE)) {
            avio_closep(&ctx.fmt_ctx->pb);
        }
        if (ctx.stream && ctx.stream->codecpar && ctx.stream->codecpar->extradata) {
            av_free(ctx.stream->codecpar->extradata);
            ctx.stream->codecpar->extradata = nullptr;
            ctx.stream->codecpar->extradata_size = 0;
        }
        avformat_free_context(ctx.fmt_ctx);
        ctx.fmt_ctx = nullptr;
        ctx.stream = nullptr;
        return -1;
    }
    av_dict_free(&opts);

    ctx.sws_ctx = sws_getContext(WIDTH, HEIGHT, AV_PIX_FMT_UYVY422,
                                 WIDTH, HEIGHT, AV_PIX_FMT_NV12,
                                 SWS_BILINEAR, NULL, NULL, NULL);
    if (!ctx.sws_ctx) {
        std::cerr << "无法初始化格式转换上下文" << std::endl;
        if (!(ctx.fmt_ctx->oformat->flags & AVFMT_NOFILE)) {
            avio_closep(&ctx.fmt_ctx->pb);
        }
        if (ctx.stream && ctx.stream->codecpar && ctx.stream->codecpar->extradata) {
            av_free(ctx.stream->codecpar->extradata);
            ctx.stream->codecpar->extradata = nullptr;
            ctx.stream->codecpar->extradata_size = 0;
        }
        avformat_free_context(ctx.fmt_ctx);
        ctx.fmt_ctx = nullptr;
        ctx.stream = nullptr;
        return -1;
    }

    ctx.is_streaming = is_streaming;
    std::cerr << "成功初始化 AVFormat 和 SwsContext: " << url << std::endl;
    return 0;
}

int rkmpp_init(const char* filename) {
    MppEncCfg cfg;
    size_t frame_size = WIDTH * HEIGHT * 3 / 2;

    if (init_mpp(cfg, frame_size) < 0) {
        cleanup_mpp(mp4_ctx);
        return -1;
    }

    if (init_avformat(mp4_ctx, filename, "mp4", false) < 0) {
        cleanup_mpp(mp4_ctx);
        mpp_enc_cfg_deinit(cfg);
        return -1;
    }

    mpp_enc_cfg_deinit(cfg);
    return 0;
}

int rkmpp_init_stream(const char* stream_url) {
    MppEncCfg cfg;
    size_t frame_size = WIDTH * HEIGHT * 3 / 2;

    rtmp_ctx.start_time = std::chrono::steady_clock::now();

    if (init_mpp(cfg, frame_size) < 0) {
        cleanup_mpp(rtmp_ctx);
        return -1;
    }

    if (init_avformat(rtmp_ctx, stream_url, "flv", true) < 0) {
        cleanup_mpp(rtmp_ctx);
        mpp_enc_cfg_deinit(cfg);
        return -1;
    }

    // 初始化调试文件
    debug_file = fopen("debug_stream.flv", "wb");
    if (!debug_file) {
        std::cerr << "无法打开调试文件 debug_stream.flv: " << strerror(errno) << std::endl;
    }

    mpp_enc_cfg_deinit(cfg);
    return 0;
}

int encode_frame(uint8_t *frame_data, int frame_count, StreamContext &ctx) {
    if (!frame_data) {
        std::cerr << "帧数据为空，帧 " << frame_count << std::endl;
        return -1;
    }
    if (!ctx.fmt_ctx || !ctx.stream || !ctx.sws_ctx) {
        std::cerr << "StreamContext 未完全初始化，帧 " << frame_count << std::endl;
        return -1;
    }
    if (!ctx.stream->codecpar) {
        std::cerr << "codecpar 未初始化，帧 " << frame_count << std::endl;
        return -1;
    }

    AVFrame *av_frame = av_frame_alloc();
    if (!av_frame) {
        std::cerr << "无法分配帧，帧 " << frame_count << std::endl;
        return -1;
    }
    av_frame->format = AV_PIX_FMT_NV12;
    av_frame->width = WIDTH;
    av_frame->height = HEIGHT;
    if (av_frame_get_buffer(av_frame, 32) < 0) {
        std::cerr << "无法分配帧缓冲区，帧 " << frame_count << std::endl;
        av_frame_free(&av_frame);
        return -1;
    }

    uint8_t *src_data[1] = { frame_data };
    int src_linesize[1] = { WIDTH * 2 };
    if (sws_scale(ctx.sws_ctx, src_data, src_linesize, 0, HEIGHT, av_frame->data, av_frame->linesize) <= 0) {
        std::cerr << "sws_scale 失败，帧 " << frame_count << std::endl;
        av_frame_free(&av_frame);
        return -1;
    }

    MppFrame mpp_frame = NULL;
    MPP_RET ret = mpp_frame_init(&mpp_frame);
    if (ret != MPP_OK) {
        mpp_err("无法初始化帧，帧 %d\n", frame_count);
        av_frame_free(&av_frame);
        return -1;
    }

    uint8_t *frm_ptr = static_cast<uint8_t*>(mpp_buffer_get_ptr_with_caller(frm_buf, __FUNCTION__));
    if (!frm_ptr) {
        std::cerr << "无法获取帧缓冲区指针，帧 " << frame_count << std::endl;
        mpp_frame_deinit(&mpp_frame);
        av_frame_free(&av_frame);
        return -1;
    }

    memcpy(frm_ptr, av_frame->data[0], WIDTH * HEIGHT);
    memcpy(frm_ptr + WIDTH * HEIGHT, av_frame->data[1], WIDTH * HEIGHT / 2);

    mpp_frame_set_width(mpp_frame, WIDTH);
    mpp_frame_set_height(mpp_frame, HEIGHT);
    mpp_frame_set_hor_stride(mpp_frame, WIDTH);
    mpp_frame_set_ver_stride(mpp_frame, HEIGHT);
    mpp_frame_set_fmt(mpp_frame, MPP_FMT_YUV420SP);
    mpp_frame_set_buffer(mpp_frame, frm_buf);
    mpp_frame_set_eos(mpp_frame, 0);

    MppPacket packet = NULL;
    ret = mpp_packet_init_with_buffer(&packet, pkt_buf);
    if (ret != MPP_OK) {
        mpp_err("无法初始化数据包，帧 %d\n", frame_count);
        mpp_frame_deinit(&mpp_frame);
        av_frame_free(&av_frame);
        return -1;
    }

    mpp_packet_set_length(packet, 0);
    MppMeta meta = mpp_frame_get_meta(mpp_frame);
    if (!meta) {
        std::cerr << "无法获取帧元数据，帧 " << frame_count << std::endl;
        mpp_packet_deinit(&packet);
        mpp_frame_deinit(&mpp_frame);
        av_frame_free(&av_frame);
        return -1;
    }
    mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet);

    {
        std::lock_guard<std::mutex> lock(mpp_mutex);
        if (!mpi || !mpp_ctx) {
            std::cerr << "MPP上下文或API未初始化，帧 " << frame_count << std::endl;
            mpp_packet_deinit(&packet);
            mpp_frame_deinit(&mpp_frame);
            av_frame_free(&av_frame);
            return -1;
        }

        ret = mpi->encode_put_frame(mpp_ctx, mpp_frame);
        if (ret != MPP_OK) {
            mpp_err("无法放入帧，帧 %d\n", frame_count);
            mpp_packet_deinit(&packet);
            mpp_frame_deinit(&mpp_frame);
            av_frame_free(&av_frame);
            return -1;
        }
    }

    mpp_frame_deinit(&mpp_frame);
    av_frame_free(&av_frame);

    {
        std::lock_guard<std::mutex> lock(mpp_mutex);
        ret = mpi->encode_get_packet(mpp_ctx, &packet);
        if (ret != MPP_OK) {
            mpp_err("无法获取数据包，帧 %d\n", frame_count);
            mpp_packet_deinit(&packet);
            return -1;
        }
    }

    if (mpp_packet_get_length(packet) > 0) {
        AVPacket *av_pkt = av_packet_alloc();
        if (!av_pkt) {
            mpp_err("无法分配AVPacket，帧 %d\n", frame_count);
            mpp_packet_deinit(&packet);
            return -1;
        }

        av_pkt->data = static_cast<uint8_t*>(mpp_packet_get_data(packet));
        av_pkt->size = mpp_packet_get_length(packet);
        av_pkt->stream_index = ctx.stream->index;

        // 使用帧计数生成 PTS/DTS
        av_pkt->pts = av_rescale_q(frame_count, (AVRational){1, FPS}, ctx.stream->time_base);
        av_pkt->dts = av_pkt->pts;

        // 标记关键帧
        if (frame_count == 0 || frame_count % (FPS / 8) == 0) {
            av_pkt->flags |= AV_PKT_FLAG_KEY;
            std::cerr << "关键帧生成，帧 " << frame_count << ", 大小: " << av_pkt->size << std::endl;
        }

        // 保存到调试文件（仅限 RTMP 流）
        if (ctx.is_streaming && debug_file) {
            fwrite(av_pkt->data, 1, av_pkt->size, debug_file);
            fflush(debug_file);
        }

        std::cerr << "帧 " << frame_count << ", PTS: " << av_pkt->pts << ", DTS: " << av_pkt->dts << ", 大小: " << av_pkt->size << std::endl;

        {
            std::lock_guard<std::mutex> lock(mpp_mutex);
            if (av_interleaved_write_frame(ctx.fmt_ctx, av_pkt) < 0) {
                std::cerr << "写入数据包失败，帧 " << frame_count << "\n";
                av_packet_free(&av_pkt);
                mpp_packet_deinit(&packet);
                return -1;
            }
        }

        av_packet_free(&av_pkt);
    }

    mpp_packet_deinit(&packet);
    return 0;
}

int encode_and_write_frame(uint8_t* frame_data, int frame_count) {
    std::lock_guard<std::mutex> lock(rtmp_ctx_mutex);
    return encode_frame(frame_data, frame_count, mp4_ctx);
}

int encode_and_stream_frame(uint8_t* frame_data, int frame_count) {
    std::lock_guard<std::mutex> lock(rtmp_ctx_mutex);
    return encode_frame(frame_data, frame_count, rtmp_ctx);
}

int save_snapshot(uint8_t* frame_data, const char* filename) {
    if (!frame_data) {
        std::cerr << "快照帧数据为空" << std::endl;
        return -1;
    }

    const AVCodec *jpeg_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
    if (!jpeg_codec) {
        std::cerr << "未找到JPEG编码器" << std::endl;
        return -1;
    }

    AVCodecContext *jpeg_ctx = avcodec_alloc_context3(jpeg_codec);
    if (!jpeg_ctx) {
        std::cerr << "无法分配JPEG编码上下文" << std::endl;
        return -1;
    }
    jpeg_ctx->width = WIDTH;
    jpeg_ctx->height = HEIGHT;
    jpeg_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
    jpeg_ctx->time_base = (AVRational){1, FPS};
    av_opt_set_int(jpeg_ctx->priv_data, "q", 2, 0);

    if (avcodec_open2(jpeg_ctx, jpeg_codec, NULL) < 0) {
        std::cerr << "无法打开JPEG编码器" << std::endl;
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }

    SwsContext *sws_ctx = sws_getContext(WIDTH, HEIGHT, AV_PIX_FMT_UYVY422,
                                         WIDTH, HEIGHT, AV_PIX_FMT_YUV420P,
                                         SWS_BILINEAR, NULL, NULL, NULL);
    if (!sws_ctx) {
        std::cerr << "无法初始化拍照转换上下文" << std::endl;
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }

    AVFrame *frame = av_frame_alloc();
    if (!frame) {
        std::cerr << "无法分配帧" << std::endl;
        sws_freeContext(sws_ctx);
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }
    frame->format = AV_PIX_FMT_YUV420P;
    frame->width = WIDTH;
    frame->height = HEIGHT;
    if (av_frame_get_buffer(frame, 32) < 0) {
        std::cerr << "无法分配帧缓冲区" << std::endl;
        av_frame_free(&frame);
        sws_freeContext(sws_ctx);
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }

    uint8_t *src_data[1] = {frame_data};
    int src_linesize[1] = {WIDTH * 2};
    sws_scale(sws_ctx, src_data, src_linesize, 0, HEIGHT, frame->data, frame->linesize);

    AVPacket *pkt = av_packet_alloc();
    if (!pkt) {
        std::cerr << "无法分配数据包" << std::endl;
        av_frame_free(&frame);
        sws_freeContext(sws_ctx);
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }

    if (avcodec_send_frame(jpeg_ctx, frame) < 0) {
        std::cerr << "发送帧到编码器失败" << std::endl;
        av_packet_free(&pkt);
        av_frame_free(&frame);
        sws_freeContext(sws_ctx);
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }

    if (avcodec_receive_packet(jpeg_ctx, pkt) < 0) {
        std::cerr << "无法接收JPEG数据包" << std::endl;
        av_packet_free(&pkt);
        av_frame_free(&frame);
        sws_freeContext(sws_ctx);
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }

    FILE *file = fopen(filename, "wb");
    if (!file) {
        std::cerr << "无法打开快照文件: " << strerror(errno) << std::endl;
        av_packet_free(&pkt);
        av_frame_free(&frame);
        sws_freeContext(sws_ctx);
        avcodec_free_context(&jpeg_ctx);
        return -1;
    }
    fwrite(pkt->data, 1, pkt->size, file);
    fclose(file);

    av_packet_free(&pkt);
    av_frame_free(&frame);
    sws_freeContext(sws_ctx);
    avcodec_free_context(&jpeg_ctx);
    return 0;
}

void cleanup_mpp(StreamContext &ctx) {
    std::lock_guard<std::mutex> lock(mpp_mutex);
    if (mpi && mpp_ctx) {
        MppFrame frame = NULL;
        MPP_RET ret = mpp_frame_init(&frame);
        if (ret == MPP_OK) {
            mpp_frame_set_eos(frame, 1);
            mpi->encode_put_frame(mpp_ctx, frame);
            mpp_frame_deinit(&frame);

            while (1) {
                MppPacket packet = NULL;
                ret = mpp_packet_init_with_buffer(&packet, pkt_buf);
                if (ret != MPP_OK)
                    break;

                ret = mpi->encode_get_packet(mpp_ctx, &packet);
                if (ret != MPP_OK) {
                    mpp_packet_deinit(&packet);
                    break;
                }

                if (mpp_packet_get_length(packet) > 0 && ctx.fmt_ctx) {
                    AVPacket *av_pkt = av_packet_alloc();
                    if (av_pkt) {
                        av_pkt->data = static_cast<uint8_t*>(mpp_packet_get_data(packet));
                        av_pkt->size = mpp_packet_get_length(packet);
                        av_pkt->stream_index = ctx.stream->index;
                        av_pkt->pts = av_pkt->dts = AV_NOPTS_VALUE;

                        av_interleaved_write_frame(ctx.fmt_ctx, av_pkt);
                        av_packet_free(&av_pkt);
                    }
                }

                if (mpp_packet_get_eos(packet)) {
                    mpp_packet_deinit(&packet);
                    break;
                }

                mpp_packet_deinit(&packet);
            }
        }
    }

    if (ctx.fmt_ctx) {
        if (!ctx.is_streaming) { // Skip trailer for RTMP
            std::cerr << "写入文件尾" << std::endl;
            av_write_trailer(ctx.fmt_ctx);
        }
        if (!(ctx.fmt_ctx->oformat->flags & AVFMT_NOFILE)) {
            std::cerr << "关闭 AVIO 上下文" << std::endl;
            avio_closep(&ctx.fmt_ctx->pb);
        }
        avformat_free_context(ctx.fmt_ctx);
        ctx.fmt_ctx = nullptr;
    }

    if (ctx.sws_ctx) {
        sws_freeContext(ctx.sws_ctx);
        ctx.sws_ctx = nullptr;
    }

    if (ctx.stream && ctx.stream->codecpar && ctx.stream->codecpar->extradata) {
        av_free(ctx.stream->codecpar->extradata);
        ctx.stream->codecpar->extradata = nullptr;
        ctx.stream->codecpar->extradata_size = 0;
    }

    ctx.stream = nullptr;
    ctx.is_streaming = false;

    if (mpi && mpp_ctx) {
        mpi->reset(mpp_ctx);
        mpp_destroy(mpp_ctx);
        mpp_ctx = NULL;
        mpi = NULL;
    }

    if (frm_buf) {
        mpp_buffer_put(frm_buf);
        frm_buf = NULL;
    }

    if (pkt_buf) {
        mpp_buffer_put(pkt_buf);
        pkt_buf = NULL;
    }

    if (buf_grp) {
        mpp_buffer_group_put(buf_grp);
        buf_grp = NULL;
    }

    // 关闭调试文件
    if (debug_file && ctx.is_streaming) {
        fclose(debug_file);
        debug_file = nullptr;
    }

    std::cerr << "清理完成\n";
}

void mpp_cleanup(void) {
    cleanup_mpp(mp4_ctx);
}

void mpp_cleanup_stream(void) {
    cleanup_mpp(rtmp_ctx);
}